From: George Dunlap Date: Wed, 19 Sep 2007 10:58:04 +0000 (+0100) Subject: [shadow] Be smarter about what we check to avoid unnecessary brute-force searches X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14937^2~66 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https://%22%22/%22http:/www.example.com/cgi/%22https:/%22%22?a=commitdiff_plain;h=f0ad89dd9dfe20f03c6b49845a04521086ef32a2;p=xen.git [shadow] Be smarter about what we check to avoid unnecessary brute-force searches The old code checked only if the page was still a pagetable before doing a brute-force search, rather than checking if it was still shadowed as the type indicated. This meant that if a page was shadowed as two different types, it was guaranteed to do a full brute-force search even if all references could be found by up-pointers. This checks the proper thing so that it will only do a brute-force if necessary. It also re-orders the unshadows so that higher levels are done first. In many cases, lower-level shadows will be destroyed in the process of higher-level shadows being destroyed, again saving brute-force searches. --- diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 4d1bac1516..04bc55deb4 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -1981,7 +1981,6 @@ void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int fast, int all) { struct page_info *pg = mfn_to_page(gmfn); mfn_t smfn; - u32 sh_flags; int do_locking; unsigned char t; @@ -2065,42 +2064,46 @@ void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int fast, int all) /* Search for this shadow in all appropriate shadows */ perfc_incr(shadow_unshadow); - sh_flags = pg->shadow_flags; /* Lower-level shadows need to be excised from upper-level shadows. * This call to hash_foreach() looks dangerous but is in fact OK: each * call will remove at most one shadow, and terminate immediately when * it does remove it, so we never walk the hash after doing a deletion. */ -#define DO_UNSHADOW(_type) do { \ - t = (_type); \ - smfn = shadow_hash_lookup(v, mfn_x(gmfn), t); \ - if ( unlikely(!mfn_valid(smfn)) ) \ - { \ - SHADOW_ERROR(": gmfn %#lx has flags 0x%"PRIx32 \ - " but no type-0x%"PRIx32" shadow\n", \ - mfn_x(gmfn), sh_flags, t); \ - break; \ - } \ - if ( sh_type_is_pinnable(v, t) ) \ - sh_unpin(v, smfn); \ - else \ - sh_remove_shadow_via_pointer(v, smfn); \ - if ( (pg->count_info & PGC_page_table) && !fast ) \ - hash_foreach(v, masks[t], callbacks, smfn); \ +#define DO_UNSHADOW(_type) do { \ + t = (_type); \ + if( !(pg->count_info & PGC_page_table) \ + || !(pg->shadow_flags & (1 << t)) ) \ + break; \ + smfn = shadow_hash_lookup(v, mfn_x(gmfn), t); \ + if ( unlikely(!mfn_valid(smfn)) ) \ + { \ + SHADOW_ERROR(": gmfn %#lx has flags 0x%"PRIx32 \ + " but no type-0x%"PRIx32" shadow\n", \ + mfn_x(gmfn), (uint32_t)pg->shadow_flags, t); \ + break; \ + } \ + if ( sh_type_is_pinnable(v, t) ) \ + sh_unpin(v, smfn); \ + else \ + sh_remove_shadow_via_pointer(v, smfn); \ + if( !fast \ + && (pg->count_info & PGC_page_table) \ + && (pg->shadow_flags & (1 << t)) ) \ + hash_foreach(v, masks[t], callbacks, smfn); \ } while (0) - if ( sh_flags & SHF_L1_32 ) DO_UNSHADOW(SH_type_l1_32_shadow); - if ( sh_flags & SHF_L2_32 ) DO_UNSHADOW(SH_type_l2_32_shadow); + DO_UNSHADOW(SH_type_l2_32_shadow); + DO_UNSHADOW(SH_type_l1_32_shadow); #if CONFIG_PAGING_LEVELS >= 3 - if ( sh_flags & SHF_L1_PAE ) DO_UNSHADOW(SH_type_l1_pae_shadow); - if ( sh_flags & SHF_L2_PAE ) DO_UNSHADOW(SH_type_l2_pae_shadow); - if ( sh_flags & SHF_L2H_PAE ) DO_UNSHADOW(SH_type_l2h_pae_shadow); + DO_UNSHADOW(SH_type_l2h_pae_shadow); + DO_UNSHADOW(SH_type_l2_pae_shadow); + DO_UNSHADOW(SH_type_l1_pae_shadow); #if CONFIG_PAGING_LEVELS >= 4 - if ( sh_flags & SHF_L1_64 ) DO_UNSHADOW(SH_type_l1_64_shadow); - if ( sh_flags & SHF_L2_64 ) DO_UNSHADOW(SH_type_l2_64_shadow); - if ( sh_flags & SHF_L2H_64 ) DO_UNSHADOW(SH_type_l2h_64_shadow); - if ( sh_flags & SHF_L3_64 ) DO_UNSHADOW(SH_type_l3_64_shadow); - if ( sh_flags & SHF_L4_64 ) DO_UNSHADOW(SH_type_l4_64_shadow); + DO_UNSHADOW(SH_type_l4_64_shadow); + DO_UNSHADOW(SH_type_l3_64_shadow); + DO_UNSHADOW(SH_type_l2h_64_shadow); + DO_UNSHADOW(SH_type_l2_64_shadow); + DO_UNSHADOW(SH_type_l1_64_shadow); #endif #endif